package com.jic.market.impl.mutex;

import com.alibaba.fastjson.JSON;
import com.beust.jcommander.internal.Lists;
import com.beust.jcommander.internal.Sets;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.jic.market.entity.PatchGrouponThemeEntity;
import com.jic.market.entity.PromotionEntity;
import com.jic.market.entity.base.BaseActivity;
import com.jic.market.entity.mutex.MutexModel;
import com.jic.market.entity.mutex.MutexProductEntity;
import com.jic.market.entity.mutex.MutexResultContext;
import com.jic.market.enums.FrontPromotionTypeEnum;
import com.jic.market.mapper.PatchGrouponThemeEntityMapper;
import com.jic.market.mapper.PromotionEntityMapper;
import com.jic.market.mapper.PromotionMerchantProductEntityMapper;
import com.jic.market.mapper.base.BaseActivityMapper;
import com.jic.market.service.mutex.MutexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * description: MutexServiceImpl
 * date: 2020/5/11 11:02
 * author: wangys
 * version: 1.0
 */
@Service
@Slf4j
public class MutexServiceImpl implements MutexService {
    private final static Map<Integer, List<Integer>> FRONT_TYPE_MUTEX_MAP = new ImmutableMap.Builder()
            .put(FrontPromotionTypeEnum.SINGLELY_SPECIAL.getCode(), Lists.newArrayList(1, 3))
            .build();

    @Autowired
    PromotionMerchantProductEntityMapper promotionMerchantProductEntityMapper;

    @Autowired
    PromotionEntityMapper promotionEntityMapper;

    @Autowired
    PatchGrouponThemeEntityMapper patchGrouponThemeEntityMapper;

    @Autowired
    BaseActivityMapper baseActivityMapper;
    /**
     * 校验2个活动是否互斥
     * @param sourceType
     * @param targetType
     * @return
     */
    @Override
    public Boolean checkMutex(Integer sourceType, Integer targetType){
        return getMutexFrontTypes(sourceType).contains(targetType);
    }

    /**
     * 获取互斥类型列表
     * @param sourceType
     * @return
     */
    private List<Integer> getMutexFrontTypes(Integer sourceType){
        return FrontPromotionTypeEnum.getExclusiveCodes(sourceType);
    }

    /**
     * 获取支付方式枚举
     * @param group
     * @return
     */
    private List<Integer> getMutexPayFrontTypes(Integer group){
        return FrontPromotionTypeEnum.getCodesByGroup(group,null);
    }

    @Override
    public MutexResultContext doProcessMutex(MutexModel mutexModel) {
        log.info("doProcessMutex param = {}", JSON.toJSONString(mutexModel));
        final Integer frontPromotionType = mutexModel.getFrontPromotionType();
        final Long promotionId = mutexModel.getPromotionId();
        final Integer promType = mutexModel.getPromType();
        final List<Long> productList = mutexModel.getProductList();
        if(mutexModel.getStartTime() == null || mutexModel.getEndTime() == null){
            processTime(mutexModel);
        }
        List<Integer> mutexFrontTypes = getMutexFrontTypes(frontPromotionType);
        if(mutexModel.getStartTime() == null || mutexModel.getEndTime() == null || CollectionUtils.isEmpty(mutexFrontTypes)){
            return new MutexResultContext()
                    .setNoMutexList(productList.stream().collect(Collectors.toSet()))
                    .setMutexPromotionProducts(Maps.newHashMap())
                    .setMutexList(Sets.newHashSet());
        }
        log.info("doProcessMutex frontType = {}, mutexFrontTypes = {}", frontPromotionType, mutexFrontTypes);
        MutexResultContext mutexResultContext = new MutexResultContext();
        final Set<Long> noMutexList = Sets.newHashSet();
        final Set<Long> mutexList = Sets.newHashSet();
        final Map<Long, Set<MutexProductEntity>> mutexPromotionProducts = Maps.newHashMap();
        productList.forEach(p->{
            //获取此商品有效状态下参与的活动列表（不包括 已结束、已过期、已关闭）
            Set<MutexProductEntity> ingFrontPromTypes = promotionMerchantProductEntityMapper.getIngFrontPromTypes(promotionId, p, promType);
            Set<MutexProductEntity> mutexProductEntitySet = Sets.newHashSet();
            ingFrontPromTypes.stream()
                //排除自身
                .filter(i->{return !(i.getPromType().equals(promType) && i.getPromotionId().equals(promotionId));})
                .filter(m->{
                    return (mutexModel.getStartTime().getTime() >= m.getStartTime().getTime() &&  mutexModel.getStartTime().getTime() < m.getEndTime().getTime())
                            || (mutexModel.getEndTime().getTime() >= m.getStartTime().getTime() &&  mutexModel.getEndTime().getTime() < m.getEndTime().getTime());
                })//
                .forEach(t->{
                    if(mutexFrontTypes.contains(t.getFrontPromType())){
                        mutexProductEntitySet.add(t);
                    }
                });
            if(CollectionUtils.isNotEmpty(mutexProductEntitySet)){
                mutexPromotionProducts.put(p, mutexProductEntitySet);
                mutexList.add(p);
            }else{
                noMutexList.add(p);
            }
        });

        MutexResultContext mutexResult = mutexResultContext
                .setMutexList(mutexList)
                .setNoMutexList(noMutexList)
                .setMutexPromotionProducts(mutexPromotionProducts);
        log.info("doProcessMutex param = {}, result = {}", JSON.toJSONString(mutexModel), JSON.toJSONString(mutexResult));
        return mutexResult;
    }

    private void processTime(MutexModel mutexModel) {
        Long promotionId = mutexModel.getPromotionId();
        //拼团

        if(null != mutexModel.getFrontPromotionType() && mutexModel.getFrontPromotionType().equals(FrontPromotionTypeEnum.GROUPON.getCode())){
            PatchGrouponThemeEntity promotionEntity = patchGrouponThemeEntityMapper.getById(promotionId);
            mutexModel.setEndTime(promotionEntity.getEndTime())
                    .setStartTime(promotionEntity.getStartTime());
        }else{
            PromotionEntity promotionEntity = promotionEntityMapper.queryById(promotionId);
            mutexModel.setEndTime(promotionEntity.getEndTime())
                    .setStartTime(promotionEntity.getStartTime());
//            BaseActivity promotionEntity = baseActivityMapper.queryById(String.valueOf(promotionId));
//            mutexModel.setEndTime(promotionEntity.getEndTime())
//                    .setStartTime(promotionEntity.getStartTime());
        }
    }

    @Override
    public MutexResultContext doProcessMutex(Long promotionId, List<Long> productIds) {
        PromotionEntity promotionEntity = promotionEntityMapper.queryById(promotionId);
        return doProcessMutex(
                new MutexModel()
                .setProductList(productIds)
                .setFrontPromotionType(promotionEntity.getFrontPromType())
                .setPromType(promotionEntity.getPromType())
                .setPromotionId(promotionId)
                .setStartTime(promotionEntity.getStartTime())
                .setEndTime(promotionEntity.getEndTime())
        );
    }

    @Override
    public MutexResultContext doProcessMutexByPatch(Long promotionId, List<Long> productIds) {
        PatchGrouponThemeEntity promotionEntity = patchGrouponThemeEntityMapper.getById(promotionId);
        return doProcessMutex(
                new MutexModel()
                        .setProductList(productIds)
                        .setFrontPromotionType(promotionEntity.getFrontPromType())
                        .setPromType(promotionEntity.getPromType())
                        .setPromotionId(promotionId)
                        .setStartTime(promotionEntity.getStartTime())
                        .setEndTime(promotionEntity.getEndTime())
        );
    }

    @Override
    public MutexResultContext doProcessMutexByPayment(MutexModel mutexModel) {
        log.info("doProcessMutex param = {}", JSON.toJSONString(mutexModel));
//        final Integer frontPromotionType = mutexModel.getFrontPromotionType();
        List<String> payFrontPromotionTypeList = mutexModel.getPayFrontPromotionTypeList();
        final Long promotionId = mutexModel.getPromotionId();
        final Integer promType = mutexModel.getPromType();
        final List<Long> productList = mutexModel.getProductList();
        if(mutexModel.getStartTime() == null || mutexModel.getEndTime() == null){
            processTime(mutexModel);
        }
        List<Integer> mutexFrontTypes = getMutexPayFrontTypes(7);
        if(mutexModel.getStartTime() == null || mutexModel.getEndTime() == null || CollectionUtils.isEmpty(mutexFrontTypes)){
            return new MutexResultContext()
                    .setNoMutexList(productList.stream().collect(Collectors.toSet()))
                    .setMutexPromotionProducts(Maps.newHashMap())
                    .setMutexList(Sets.newHashSet());
        }
        log.info("doProcessMutex payFrontType = {}, mutexFrontTypes = {}", payFrontPromotionTypeList, mutexFrontTypes);
        MutexResultContext mutexResultContext = new MutexResultContext();
        final Set<Long> noMutexList = Sets.newHashSet();
        final Set<Long> mutexList = Sets.newHashSet();
        final Map<Long, Set<MutexProductEntity>> mutexPromotionProducts = Maps.newHashMap();
        productList.forEach(p->{
            //获取此商品有效状态下参与的活动列表（不包括 已结束、已过期、已关闭）
            Set<MutexProductEntity> ingFrontPromTypes = promotionMerchantProductEntityMapper.getIngPayFrontPromTypes(promotionId, p, promType);
            Set<MutexProductEntity> mutexProductEntitySet = Sets.newHashSet();
            ingFrontPromTypes.stream()
                    //排除自身
                    .filter(i->{return !( i.getPromotionId().equals(promotionId));})
                    .filter(m->{
                        return (mutexModel.getStartTime().getTime() >= m.getStartTime().getTime() &&  mutexModel.getStartTime().getTime() < m.getEndTime().getTime())
                                || (mutexModel.getEndTime().getTime() >= m.getStartTime().getTime() &&  mutexModel.getEndTime().getTime() < m.getEndTime().getTime());
                    })//
                    .forEach(t->{
                        List<Integer> payFrontPromTypes = Arrays.asList(t.getPayFrontPromType().split(",")).stream()
                                .map(temp->{
                                    return Integer.valueOf(temp);
                                }).collect(Collectors.toList());
//                        if(mutexFrontTypes.contains(t.getFrontPromType())){
//                            mutexProductEntitySet.add(t);
//                        }
                        if(!Collections.disjoint(mutexFrontTypes,payFrontPromTypes)){
                            mutexProductEntitySet.add(t);
                        }
                    });
            if(CollectionUtils.isNotEmpty(mutexProductEntitySet)){
                mutexPromotionProducts.put(p, mutexProductEntitySet);
                mutexList.add(p);
            }else{
                noMutexList.add(p);
            }
        });

        MutexResultContext mutexResult = mutexResultContext
                .setMutexList(mutexList)
                .setNoMutexList(noMutexList)
                .setMutexPromotionProducts(mutexPromotionProducts);
        log.info("doProcessMutex param = {}, result = {}", JSON.toJSONString(mutexModel), JSON.toJSONString(mutexResult));
        return mutexResult;
    }

    public static void main(String[] args) {
        List<Integer> mutexFrontTypes = new ArrayList<>();
        mutexFrontTypes.add(29);
        mutexFrontTypes.add(30);
        mutexFrontTypes.add(31);
        mutexFrontTypes.add(32);
        List<Integer> payFrontPromTypes = new ArrayList<>();
        payFrontPromTypes.add(29);
        if(Collections.disjoint(mutexFrontTypes,payFrontPromTypes)){
            System.out.println("重复了");
        }
    }
}
